package io.flysium.framework.util.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import io.flysium.framework.util.ftp.FTPUtils.FtpBatchResult;
import io.flysium.framework.util.ftp.FTPUtils.FtpConfig;
import io.flysium.framework.util.ftp.FTPUtils.FtpResult;

/**
 * SFTP工具类
 * @author SvenAugustus(蔡政滦)  e-mail: SvenAugustus@outlook.com
 * @version 1.0
 */
final class SendSftpTool {

	private static Logger logger = LoggerFactory.getLogger(SendSftpTool.class);

	private SendSftpTool() {
	}

	public static Session getSftpSession(FtpConfig config) throws Exception {
		JSch jsch = new JSch();
		Session session = null;
		try {
			session = jsch.getSession(config.getUsername(), config.getIp_address(), config.getPort());
			session.setPassword(config.getPwd());
			session.setTimeout(30000);
			Properties sftpconf = new Properties();
			sftpconf.put("StrictHostKeyChecking", "no");
			session.setConfig(sftpconf);
			session.connect();
		} catch (Exception e) {
			logger.error(e.getMessage());
			return null;
		} finally {
			jsch = null;
		}
		return session;
	}

	public static ChannelSftp getSftpChannel(Session session) throws Exception {
		ChannelSftp channel = null;
		try {
			channel = (ChannelSftp) session.openChannel("sftp"); // 打开SFTP通道
			channel.connect();
		} catch (Exception e) {
			logger.error(e.getMessage());
			return null;
		}

		return channel;
	}

	public static FtpResult sendtoftp(ChannelSftp channel, FtpConfig config, File file, String remoteFileNametemp) throws Exception {
		FtpResult ftpResult = new FtpResult();
		ftpResult.setSuc(false);
		ftpResult.setRemoteFileNametemp(remoteFileNametemp);
		ftpResult.setLocalFile(file);
		BufferedInputStream buffIn = null;
		try {
			if (!"/".equals(config.getDest_dir())) {
				channel.cd(config.getDest_dir());
			}
		} catch (SftpException e1) {
			if (e1.id == 2) {
				try {
					channel.mkdir(config.getDest_dir());
				} catch (Exception e) {
					System.err.println("创建文件夹" + config.getDest_dir() + "失败：" + e.getMessage());
					return ftpResult;
				}
				channel.cd(config.getDest_dir());
			}
		}
		try {
			buffIn = new BufferedInputStream(new FileInputStream(file));
			channel.put(buffIn, remoteFileNametemp);
			ftpResult.setSuc(true);
		} catch (Exception e) {
			logger.error("SFTP上传失败", e);
			ftpResult.setSuc(false);
		} finally {
			if (null != buffIn) {
				buffIn.close();
			}
			if (ftpResult != null && ftpResult.isSuc()) {
				logger.info("ip=   " + config.getIp_address() + "  " + remoteFileNametemp + " 发送成功");
			}
		}
		return ftpResult;
	}

	public static FtpResult getofftp(ChannelSftp channel, FtpConfig config, File file, String remoteFileNametemp) throws Exception {
		FtpResult ftpResult = new FtpResult();
		ftpResult.setSuc(false);
		ftpResult.setRemoteFileNametemp(remoteFileNametemp);
		ftpResult.setLocalFile(file);
		BufferedOutputStream buffOut = null;
		try {
			if (!"/".equals(config.getDest_dir())) {
				channel.cd(config.getDest_dir());
			}
		} catch (SftpException e1) {
			if (e1.id == 2) {
				channel.cd(config.getDest_dir());
			}
		}
		try {
			buffOut = new BufferedOutputStream(new FileOutputStream(file));
			channel.get(remoteFileNametemp, buffOut);
			ftpResult.setSuc(true);
		} catch (Exception e) {
			logger.error("SFTP下载失败", e);
			ftpResult.setSuc(false);
		} finally {
			if (null != buffOut) {
				buffOut.close();
			}
			if (ftpResult != null && ftpResult.isSuc()) {
				logger.info("ip=   " + config.getIp_address() + "  " + remoteFileNametemp + " 下载成功");
			}
		}
		return ftpResult;
	}

	@SuppressWarnings({"rawtypes", "unchecked"})
	public static FtpBatchResult batchGetofftp(ChannelSftp channel, FtpConfig config, FTPFileFilter ftpFileFilter, boolean rmIfSuc,
			boolean interruptIfError) throws Exception {
		FtpBatchResult ftpBatchResult = new FtpBatchResult(true, new ArrayList<FtpResult>());
		try {
			if (!"/".equals(config.getDest_dir())) {
				channel.cd(config.getDest_dir());
			}
		} catch (SftpException e1) {
			if (e1.id == 2) {
				channel.cd(config.getDest_dir());
			}
		}
		try {
			Vector<LsEntry> fileList = channel.ls(config.getDest_dir());
			if (fileList != null) {
				Iterator it = fileList.iterator();
				while (it.hasNext()) {
					LsEntry f = (LsEntry) it.next();
					String remoteFileNametemp = f.getFilename();
					if (ftpFileFilter == null || (ftpFileFilter != null && ftpFileFilter.filter(remoteFileNametemp))) {
						File localFile = new File(config.getLocal_bak_dir(), remoteFileNametemp);
						BufferedOutputStream buffOut = null;
						try {
							buffOut = new BufferedOutputStream(new FileOutputStream(localFile));
							channel.get(remoteFileNametemp, buffOut);//文件取到本地
							buffOut.close();
							ftpBatchResult.getResult().add(new FtpResult(true, remoteFileNametemp, localFile));
							logger.info("ip=   " + config.getIp_address() + "  " + config.getDest_dir() + "/" + remoteFileNametemp + " 下载成功");
						} catch (Exception e) {
							ftpBatchResult.setSuc(false);
							ftpBatchResult.getResult().add(new FtpResult(false, remoteFileNametemp, localFile));
							if (interruptIfError) {
								throw e;
							}
						} finally {
							if (null != buffOut) {
								buffOut.close();
							}
						}
						if (rmIfSuc) {// 是否文件下载后删除远程ftp文件
							channel.rm(remoteFileNametemp);
						}
					}
				}
			}
		} catch (Exception e) {
			ftpBatchResult.setSuc(false);
			logger.error("SFTP下载失败", e);
		} finally {
			if (ftpBatchResult != null && ftpBatchResult.isSuc()) {
				logger.info("ip=   " + config.getIp_address() + "  " + config.getDest_dir() + " 下载成功");
			}
		}
		return ftpBatchResult;
	}
}
